package com.polaris.live.ui.party.widget.videoseat

import android.view.TextureView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.faceunity.wrapper.faceunity
import com.polaris.live.ui.party.widget.videoseat.listener.VideoStreamManageListener
import com.polaris.live.utils.zego.LiveEngineManage
import com.polaris.live.utils.zego.PublishingStreamProxy
import com.polaris.live.utils.zego.beauty.FaceManager
import com.polaris.live.utils.zego.beauty.FaceUnity
import im.zego.zegoexpress.ZegoExpressEngine
import im.zego.zegoexpress.callback.IZegoCustomVideoProcessHandler
import im.zego.zegoexpress.callback.IZegoEventHandler
import im.zego.zegoexpress.constants.ZegoPublishChannel
import im.zego.zegoexpress.constants.ZegoVideoConfigPreset
import im.zego.zegoexpress.constants.ZegoVideoMirrorMode
import im.zego.zegoexpress.constants.ZegoViewMode
import im.zego.zegoexpress.entity.ZegoCanvas
import im.zego.zegoexpress.entity.ZegoVideoConfig
import java.util.concurrent.ConcurrentHashMap


/**
 *  视频聊天室流管理PartyVideoStreamProxy
 * @author Created by 天晴 on 2024/6/21 19:17
 * @since 1.0.0
 **/
class PartyVideoStreamProxy {
    private val faceUnity: FaceUnity = FaceManager.createFaceUnity()
    private var lastFaceTrackingTime: Long? = null
    private var useFrontCamera: Boolean = true //是否使用前置摄像头
    private var cameraOpen: Boolean? = null //摄像头是否打开
    fun observe(owner: LifecycleOwner) {
        faceUnity.observe(owner)
        owner.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    faceUnity.onReleaseUnity()
                    engine?.setCustomVideoProcessHandler(null)
                }
            }
        })
    }

    var mStreamManageListener: VideoStreamManageListener? = null
    private val eventHandler = object : IZegoEventHandler() {
        /**
         * 自己本地监听音浪
         */
        override fun onCapturedSoundLevelUpdate(soundLevel: Float) {
            super.onCapturedSoundLevelUpdate(soundLevel)
            mStreamManageListener?.onCapturedSoundLevelUpdate(soundLevel)
        }

        /**
         * 远端拉流音频声浪回调
         *
         * 回调通知周期为 100 ms。
         * @param soundLevels 远端的声浪键值对，key 为流 ID，value 为对应的流的声浪值，value 取值范围为 0.0 ~ 100.0
         */
        override fun onRemoteSoundLevelUpdate(soundLevels: HashMap<String, Float>?) {
            super.onRemoteSoundLevelUpdate(soundLevels)
            soundLevels?.let {
                soundLevels.forEach { map ->
                    getKeyFromValue(playingList, map.key)?.let { seatId ->
                        mStreamManageListener?.onRemoteSoundLevelUpdate(seatId, map.value)
                    }

                }
            }
        }

    }

    fun <K, V> getKeyFromValue(map: Map<K, V>, value: V): K? {
        for ((key, value1) in map.entries) {
            if (value == value1) {
                return key
            }
        }
        return null
    }

    var engine: ZegoExpressEngine? = null


    /**
     * 加入房间添加回调
     */
    fun setJoinRoom(mVideoStreamManageListener: VideoStreamManageListener) {
        engine = LiveEngineManage.getEngine()
        this.mStreamManageListener = mVideoStreamManageListener
        LiveEngineManage.eventHandlerHelper.addEventHandler(eventHandler)
        //启动监听声浪
        engine?.startSoundLevelMonitor(500);
    }


    /**
     * 播放中的流
     */
    val playingList = ConcurrentHashMap<Int, String>()


    /**
     * 开启流
     */
    fun openStream(seatId: Int, streamId: String, publishView: TextureView) {
        val mStreamId = playingList[seatId]
        if (mStreamId == null) {
            startStream(streamId, publishView)
            playingList[seatId] = streamId
        } else {
            //流ID不一样切换
            if (streamId != mStreamId) {
                closeStreamsBySeatId(seatId)
                startStream(streamId, publishView)
                playingList[seatId] = streamId
            }
        }
    }


    fun switchTextureView() {

    }

    private fun startStream(streamId: String, publishView: TextureView) {
        val playCanvas = ZegoCanvas(publishView).apply {
            viewMode = ZegoViewMode.ASPECT_FILL
        }
        engine?.startPlayingStream(streamId, playCanvas)

    }

    /**
     * 将指定位置上得流关闭
     */
    fun closeStreamsBySeatId(seatId: Int) {
        playingList[seatId]?.let {
            engine?.stopPlayingStream(it)
        }
        playingList.remove(seatId)
    }


    /**
     * 清除全部流
     */
    fun clearStreams() {
        playingList.forEach { a ->
            engine?.stopPlayingStream(a.value)
        }
        playingList.clear()
    }


    var streamId: String? = null
    var audio: Boolean? = null
    var video: Boolean? = null
    var publishView: TextureView? = null

    /**
     *
     * 发布自己的流
     */
    fun publishStream(streamId: String, audio: Boolean, video: Boolean, publishView: TextureView) {
        if (this.streamId != streamId) {
            stopPublishStream()
            PublishingStreamProxy.start(hashCode(), streamId) {
                if (it) {
                    engine?.muteMicrophone(!audio)
                    engine?.enableCamera(video)
                    registerBeauty()

                    val previewCanvas = ZegoCanvas(publishView).apply {
                        viewMode = ZegoViewMode.ASPECT_FILL
                    }

                    engine?.startPreview(previewCanvas)
                    engine?.startPublishingStream(streamId)
                    //默认设置为180P
                    engine?.videoConfig = ZegoVideoConfig(ZegoVideoConfigPreset.PRESET_180P)
                    engine?.setVideoMirrorMode(ZegoVideoMirrorMode.ONLY_PREVIEW_MIRROR)
                    engine?.useFrontCamera(useFrontCamera)
                    this.streamId = streamId
                    this.audio = audio
                    this.video = video
                    this.publishView = publishView
                }
            }
        } else {
            if (!this.streamId.isNullOrEmpty()) {
                if (this.audio != audio) {
                    engine?.muteMicrophone(!audio)
                    this.audio = audio
                }
                if (this.video != video) {
                    engine?.enableCamera(video)
                    this.video = video
                }
                if (this.publishView != publishView) {
                    val previewCanvas = ZegoCanvas(publishView).apply {
                        viewMode = ZegoViewMode.ASPECT_FILL
                    }
                    engine?.startPreview(previewCanvas)
                    this.publishView = publishView
                }
            }
        }
        cameraOpen = video
    }

    fun onSwitchCamera() {
        streamId?.let {
            audio?.let {
                publishView?.let {
                    useFrontCamera = !useFrontCamera
                    engine?.useFrontCamera(useFrontCamera)
                    if (useFrontCamera) {
                        engine?.setVideoMirrorMode(ZegoVideoMirrorMode.ONLY_PREVIEW_MIRROR)
                    } else {
                        engine?.setVideoMirrorMode(ZegoVideoMirrorMode.NO_MIRROR)
                    }
                }
            }
        }
    }

    fun getIsOpenCamera(): Boolean {
        return cameraOpen == true
    }

    /**
     * 注册美颜配置
     */
    private fun registerBeauty() {
        engine?.setCustomVideoProcessHandler(object : IZegoCustomVideoProcessHandler() {
            override fun onCapturedUnprocessedTextureData(
                textureID: Int,
                width: Int,
                height: Int,
                referenceTimeMillisecond: Long,
                channel: ZegoPublishChannel?,
            ) {

                val texId = faceUnity.renderToTexture(textureID, width, height)
                engine?.sendCustomVideoProcessedTextureData(
                    texId,
                    width,
                    height,
                    referenceTimeMillisecond
                )

                val lastFaceTrackingTime = lastFaceTrackingTime
                val currentTime = System.currentTimeMillis()
                if (lastFaceTrackingTime == null || currentTime - lastFaceTrackingTime > 1000) {
                    onChangeFace(faceunity.fuIsTracking())
                    this@PartyVideoStreamProxy.lastFaceTrackingTime = currentTime
                }
            }

        })
    }

    private fun onChangeFace(tracking: Int) {
//        if (onFaceStateChangeListener == null) return
//
//        if (tracking != lastFaceNumber) {
//            val valid = tracking > 0
//            viewModel.viewModelScope.launch {
//                onFaceStateChangeListener.onFaceStateChange(valid)
//            }
//        }
//
//        lastFaceNumber = tracking
    }

    /**
     *
     * 停止发布自己的流
     */
    fun stopPublishStream() {
        PublishingStreamProxy.checkState(hashCode(), streamId) {
            if (it) {
                engine?.enableCamera(false)
                engine?.muteMicrophone(true)
                streamId?.let {
                    engine?.stopPreview()
                    engine?.stopPublishingStream()
                }
            }
        }
        streamId = null
        cameraOpen = null
        audio = null
        video = null
        publishView = null
    }


    fun destroyStreams() {
        // 停止监听声浪
        engine?.stopSoundLevelMonitor();
        LiveEngineManage.eventHandlerHelper.removeEventHandler(eventHandler)
        stopPublishStream()
        clearStreams()
        engine = null
    }


}